import {
    _decorator,
    Button,
    Camera,
    Component,
    director,
    EventTouch,
    instantiate,
    Label,
    Layout,
    macro,
    Node,
    Prefab,
    Quat,
    resources,
    ScrollView,
    Size,
    Sprite,
    TiledLayer,
    tween,
    UITransform,
    Vec2,
    Vec3
} from "cc"
import {GameEvent} from "db://assets/script/game-event";
import {CityBuildingMove} from "db://assets/script/common/events/city-events/city-building-move";
import {CityBuildingBeginEdit} from "db://assets/script/common/events/city-events/city-building-begin-edit";
import {CityBuildingPrePut} from "db://assets/script/common/events/city-events/city-building-pre-put";
import {CityBuildingPreRemove} from "db://assets/script/common/events/city-events/city-building-pre-remove";
import {NormalBuildingStatus} from "db://assets/script/game/constants/normal-building-status";
import LabelTime from "db://assets/script/common/label-time";
import {BuildingItem} from "db://assets/proto/new-world-api/v1/building";
import {BuildingStatus} from "db://assets/proto/shared/v1/wuni";
import {CityBuildingCheckUpgrade} from "db://assets/script/common/events/city-events/city-building-check-upgrade";
import {CityBuildingCheckRemove} from "db://assets/script/common/events/city-events/city-building-check-remove";
import Long from "long";
import {CityBuildingPreUpgrade} from "db://assets/script/common/events/city-events/city-building-pre-upgrade";
import {serverTimeHelper} from "db://assets/script/server-time-helper";
import {configsHelper} from "db://assets/script/configs-helper";
import {cityUtils} from "db://assets/script/utils/city-utils";
import {CityBuildingCancelEdit} from "db://assets/script/common/events/city-events/city-building-cancel-edit";
import calcBuildingScaleInWorld = cityUtils.calcBuildingScaleInWorld;
import calcCellId = cityUtils.calcCellId;
import {userInfo} from "db://assets/script/user-info";
import {lobby} from "db://assets/script/lobby";
import {ProducePlane} from "db://assets/script/game/mainui/city/produce-plane";
import {showAlert} from "db://assets/script/game/alert/alert";
import {utils} from "db://assets/script/utils/utils";
import {FishFryTop} from "db://assets/script/game/mainui/city/fish-fry-top";
import {DormitoryPlane} from "db://assets/script/game/mainui/city/dormitory-plane";
import {AssetId} from "db://assets/proto/shared/v1/props";
import {BuildingConfigs, BuildingUpgradeConfigs} from "db://assets/proto/shared/v1/configs";
import {propsConfigsLoader} from "db://assets/script/configs/props-configs-loader";
import calcBuildingIcon = cityUtils.calcBuildingIcon;
import {MixingReceive} from "db://assets/script/common/events/mix-events/mixing-receive";
import {PropItem} from "db://assets/script/game/mainui/props/prop-item";
import {UserLevelUpEvent} from "db://assets/script/common/events/asset-events/user-level-up-event";

const {ccclass, property} = _decorator

@ccclass('NormalBuilding')
export class NormalBuilding extends Component {

    @property(Sprite)
    building!: Sprite

    @property(Sprite)
    buildingShadow!: Sprite

    @property(Layout)
    checkBox!: Layout

    @property(Button)
    checkButton!: Button

    @property(Button)
    cancelButton!: Button

    @property(Button)
    upgradeButton!: Button

    @property(Sprite)
    completeAtMsLabelBg!: Sprite

    @property(LabelTime)
    completeAtMsLabel!: LabelTime

    @property(Label)
    levelLabel!: Label

    @property(Node)
    levelBg!: Node

    @property(Sprite)
    resourcePop!: Sprite

    @property(Sprite)
    resourceIcon!: Sprite

    @property(Node)
    clickBox!: Node

    @property(Label)
    numLabel!: Label

    @property(Node)
    numBox!: Node

    @property(Node)
    upgradeFlagIcon!: Node

    _direction: number = 1
    _status: number = 0
    buildingId: Long = Long.fromNumber(0)
    tiledX: number = 0
    tiledY: number = 0
    buildingItem: BuildingItem | null = null
    currentMoveX: number = 0
    currentMoveY: number = 0
    tiledLayer: TiledLayer | null = null
    tileSize!: Size
    inWhichScrollView: ScrollView | null = null
    buildingOffsetY: number = 0
    buildingOffsetX: number = 0
    newBuilding: boolean = true

    removable = true
    movable = true
    resourceBuilding = false
    buildingConfig: BuildingConfigs | null = null
    latestIdx: number = 0

    start() {
    }


    loadBuilding(buildingId: Long, buildingItem: BuildingItem | null, tiledLayer: TiledLayer | null) {
        const sf = calcBuildingIcon(buildingId)!
        const originBuildingWidth = sf.originalSize.width
        const originBuildingHeight = sf.originalSize.height
        this.building.spriteFrame = sf
        const config = configsHelper.loadBuildingConfig(buildingId)!
        this.buildingConfig = config
        const size = new Size(config.width, config.height)
        const worldSize = calcBuildingScaleInWorld(size)
        this.buildingId = buildingId
        this.tiledLayer = tiledLayer
        this.completeAtMsLabel.zeroize = false
        this.resourcePop.node.active = false
        if (buildingItem) this.resourceBuilding = configsHelper.checkResourceBuilding(buildingId, buildingItem!.level)
        if (buildingItem) {
            this.buildingItem = buildingItem
            if (buildingItem.completeAtMs.gt(0)) {
                if (buildingItem.status == BuildingStatus.Upgrading) this.beginUpgrade()
                else this.beginRemove()
            }
        }
        this.schedule(() => this._tryShowResourcePop(), 1, macro.REPEAT_FOREVER)

        if (originBuildingHeight > originBuildingWidth) {
            const scale = originBuildingHeight / 128
            this.building.getComponent(UITransform)!.setContentSize(new Size(originBuildingWidth * worldSize.width / scale, 128 * worldSize.height))
        } else {
            const scale = originBuildingWidth / 128
            this.building.getComponent(UITransform)!.setContentSize(new Size(128 * worldSize.width, originBuildingHeight * worldSize.height / scale))
        }
        this.upgradeFlagIcon.x = this.getComponent(UITransform)!.width * this.calculateOriginPercentage(this.buildingConfig!.width, this.buildingConfig!.height) + 5
        this.upgradeFlagIcon.y = 5
        this.removable = config.removable
        this.movable = config.movable
        this.clickBox.active = false
        this.building.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this)
        this.building.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this)
        this.building.node.on(Node.EventType.TOUCH_END, this.onTouchEnd, this)
        this.building.node.on(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this)
        this.checkButton.node.on(Button.EventType.CLICK, this.checkEdit, this)
        this.cancelButton.node.on(Button.EventType.CLICK, this.cancelEdit, this)
        this.upgradeButton.node.on(Button.EventType.CLICK, this.upgrade, this)
        this.resourcePop.node.on(Node.EventType.TOUCH_END, this.resourceTryReceive, this)
        tween(this.resourcePop.node)
            .to(0.5, {scale: new Vec3(1.1, 1.1, 1.1)})
            .to(0.5, {scale: new Vec3(1, 1, 1)})
            .union()
            .repeatForever()
            .start();
        this.onEvent()
        this.updateUI(this.buildingItem?.buildingUniqueId)
    }

    onEvent() {
        director.on(GameEvent.uiUpdateCity, this.updateUI, this)
        director.on(GameEvent.cityChangeInEdit, this._onChangeEdit, this)
        director.on(GameEvent.userLevelUp, this._onUserLevelUp, this)
    }

    offEvent() {
        director.off(GameEvent.uiUpdateCity, this.updateUI, this)
        director.off(GameEvent.cityChangeInEdit, this._onChangeEdit, this)
        director.off(GameEvent.userLevelUp, this._onUserLevelUp, this)
    }

    private _onChangeEdit() {
        this._tryShowResourcePop()
        if (this._status == NormalBuildingStatus.edit || this._status == NormalBuildingStatus.in_see) {
            if (this.newBuilding) {
                this.cancelEdit()
            } else {
                this.checkEdit()
            }
        }
    }

    private _tryShowResourcePop() {
        if (this.resourceBuilding && this.buildingItem && this.buildingId && !userInfo.cityInfo.checkInEdit()) {
            const pipeTag = 'pipe_tag:building:1:' + this.buildingId.toString()
            const mixInfo = userInfo.mixInfo.loadMixInfo(pipeTag, this.buildingItem.buildingUniqueId)
            if (mixInfo) {
                const bac = configsHelper.loadBuildingMixingFormulaConfigs(this.buildingId, this.buildingItem.level)
                if (bac) {
                    const nowMs = serverTimeHelper.loadServerTime()
                    const beginAtMs = mixInfo.beginAtMs.add(mixInfo.beginAtMsOffset).toNumber()
                    const costMs = bac.costMs.toNumber()
                    const completeAtMs = mixInfo.completeAtMs.toNumber()
                    const endAtMs = completeAtMs < nowMs ? completeAtMs : nowMs
                    const currentOffset = endAtMs - beginAtMs
                    const producePre = currentOffset / costMs
                    if (producePre >= 5) {
                        for (let reward of bac.successShowOutput) {
                            const pf = propsConfigsLoader.findPropIcon(reward.propId.toNumber())
                            if (pf) {
                                this.resourceIcon.spriteFrame = pf!
                                this.resourcePop.node.active = true
                                break
                            }
                        }
                    } else {
                        this.resourcePop.node.active = false
                    }
                } else {
                    this.resourcePop.node.active = false
                }
            } else {
                this.resourcePop.node.active = false
            }
        } else {
            this.resourcePop.node.active = false
        }
    }

    cancelEdit() {
        if (this.newBuilding) {
            director.emit(GameEvent.cityBuildingCancelEdit, new CityBuildingCancelEdit(this, true))
            this.node.destroy()
        } else {
            director.emit(GameEvent.cityBuildingPreRemove, new CityBuildingPreRemove(this.buildingItem!))
        }
    }

    checkEdit() {
        if (this.newBuilding) {
            const upgradeConfigs = configsHelper.loadBuildingUpgradeConfig(this.buildingId, 1)
            if (upgradeConfigs) {
                if (upgradeConfigs.requiredRewards.length == 0) {
                    director.emit(GameEvent.cityBuildingPrePut, new CityBuildingPrePut(this, {}))
                } else {
                    this.showUpgradeOrBuildAlert(1, upgradeConfigs)
                }
            }
        } else {
            if (this.movable && (this.tiledX != this.buildingItem!.x || this.tiledY != this.buildingItem!.y)) {
                director.emit(GameEvent.cityBuildingPreMovePut, new CityBuildingPrePut(this, {}))
            } else {
                this.changeStatus(NormalBuildingStatus.normal)
                director.emit(GameEvent.cityBuildingCancelEdit, new CityBuildingCancelEdit(this, false))
            }
        }
    }

    resourceTryReceive() {
        if (this.buildingItem) {
            director.emit(GameEvent.mixingTryReceive, new MixingReceive('pipe_tag:building:1:' + this.buildingId.toString(), this.buildingItem!.buildingUniqueId, this.buildingItem.level))
        }
    }

    upgrade() {
        if (!this.canUpgrade()) {
            lobby.instance.showToast('该建筑等级达到上限')
            return;
        }
        const upgradeConfigs = configsHelper.loadBuildingUpgradeConfig(this.buildingId, this.buildingItem!.level + 1)
        if (upgradeConfigs) this.showUpgradeOrBuildAlert(this.buildingItem!.level + 1, upgradeConfigs)
    }

    _onUserLevelUp(event: UserLevelUpEvent) {
        this.upgradeFlagIcon.active = this.canUpgrade()
    }

    canUpgrade(): boolean {
        if (!this.newBuilding && this.buildingItem && this.buildingItem!.status == BuildingStatus.NORMAL) {
            const userLevel = userInfo.loadUserLevel()
            const levelLimit = configsHelper.loadUserLevelBuildingLevelLimit(userLevel, this.buildingId)
            if (levelLimit == Number.MAX_SAFE_INTEGER) return false
            return this.buildingItem.level < levelLimit;
        }
        return false
    }

    showUpgradeOrBuildAlert(level: number, upgradeConfigs: BuildingUpgradeConfigs) {
        const assetTips: string[] = []
        for (let pp of upgradeConfigs.requiredRewards) {
            const ac = configsHelper.loadAssetConfig(pp.propId.toNumber())
            if (ac) {
                assetTips.push(ac.name + ' x ' + Math.floor(pp.num.toNumber()))
            }
        }
        const aac = configsHelper.loadBuildingAssetConfig(this.buildingId)
        let content = '是否消耗资产：' + assetTips.join(",")
        content += '\n耗时：' + utils.timeDurationFormat(upgradeConfigs.costMs.toNumber())
        const typeTag = level == 1 ? '建造' : '升级'
        if (level == 1) content += '建造「' + aac?.name + '」?'
        else content += '升级「' + aac?.name + '」?'
        // content += typeTag + '「' + aac?.name + '」?'
        showAlert(typeTag, content, () => {
            const costAssets: { [key: number]: Long } = {}
            for (let rp of upgradeConfigs.requiredRewards) {
                costAssets[rp.propId.toNumber()] = rp.num.mul(-1)
            }
            level == 1 ?
                director.emit(GameEvent.cityBuildingPrePut, new CityBuildingPrePut(this, costAssets)) :
                director.emit(GameEvent.cityBuildingPreUpgrade, new CityBuildingPreUpgrade(this.buildingItem!, costAssets))
        }, () => {
            lobby.instance.showClickMaskWithNode(this.node, 0, () => this.checkEdit())
        })
    }

    tryProduce() {
        if (this.buildingItem && this.buildingItem!.status == BuildingStatus.NORMAL) {
            const producePlane = lobby.instance.addUIWithClickMask('prefab/common/produce-plane', 0, (node) => node.destroy())
            producePlane.getComponent(ProducePlane)!.init(this)
        }
    }

    changeStatus(status: number) {
        this._status = status
        switch (status) {
            case NormalBuildingStatus.normal:
                this._changeStatus2Normal()
                break
            case NormalBuildingStatus.edit:
                this._changeStatus2Edit()
                break
            case NormalBuildingStatus.show:
                this._changeStatus2Show()
                break
            case NormalBuildingStatus.in_see:
                this._changeStatus2InSee()
                break
        }
    }

    _changeStatus2Show() {
        const sf = this.building.spriteFrame!
        const originBuildingWidth = sf.originalSize.width
        const originBuildingHeight = sf.originalSize.height
        if (originBuildingHeight > originBuildingWidth) {
            const scale = originBuildingHeight / 128
            this.building.getComponent(UITransform)!.setContentSize(new Size(originBuildingWidth / scale, 128))
        } else {
            const scale = originBuildingWidth / 128
            this.building.getComponent(UITransform)!.setContentSize(new Size(128, originBuildingHeight / scale))
        }
        this.node.setScale(0.7, 0.7)
        this.building.node.setScale(1, 1)
        this.getComponent(Sprite)!.enabled = true
        this.checkBox.node.active = false
        this.numBox.active = false
        userInfo.cityInfo.loadBuildingsNum(1, this.buildingId)
        let exp = userInfo.assetInfo.assets[AssetId.asset_id_exp]
        if (!exp) exp = Long.fromNumber(0)
        const userLevel = configsHelper.loadUserLevelByExp(exp)
        const limit = configsHelper.loadUserLevelBuildingNumLimit(userLevel, this.buildingId)
        if (limit) {
            this.numBox.active = true
            const bNum = userInfo.cityInfo.loadBuildingsNum(1, this.buildingId)
            if (bNum >= limit) this.numLabel.string = '已满'
            else this.numLabel.string = bNum + '/' + limit
        }
    }

    _changeStatus2Edit() {
        console.log('changeStatus2Edit', this)
        this.node.setScale(1, 1)
        this.building.node.position = new Vec3(this.buildingOffsetX, this.buildingOffsetY)
        this.getComponent(Sprite)!.enabled = false
        this.checkBox.node.active = true
        this.checkButton.node.active = true
        this.upgradeButton.node.active = false
        if (this.buildingItem?.status == BuildingStatus.NORMAL) {
            this.cancelButton.node.active = this.removable
        } else if (this.buildingItem?.status == BuildingStatus.Upgrading) {
            this.cancelButton.node.active = false
        } else if (this.buildingItem?.status == BuildingStatus.REMOVING) {
            this.cancelButton.node.active = false
        }
        this.numBox.active = false
        this.node.setSiblingIndex(Number.MAX_SAFE_INTEGER)
        lobby.instance.showClickMaskWithNode(this.node, 0, () => this.checkEdit())
    }

    _changeStatus2InSee() {
        console.log('changeStatus2InSee', this)
        this.node.setScale(1.1, 1.1)
        this.building.node.position = new Vec3(this.buildingOffsetX, this.buildingOffsetY - 50)
        this.getComponent(Sprite)!.enabled = false
        this.checkBox.node.active = true
        this.cancelButton.node.active = false
        this.checkButton.node.active = false
        if (this.buildingItem?.status == BuildingStatus.NORMAL) {
            const upgradeConfigs = configsHelper.loadBuildingUpgradeConfig(this.buildingId, this.buildingItem!.level + 1)
            this.upgradeButton.node.active = upgradeConfigs != undefined
            const buildingConfigs = configsHelper.loadBuildingConfig(this.buildingId)
            this.cancelButton.node.active = buildingConfigs.removable
        } else if (this.buildingItem?.status == BuildingStatus.Upgrading) {
            this.upgradeButton.node.active = false
        } else if (this.buildingItem?.status == BuildingStatus.REMOVING) {
            this.upgradeButton.node.active = false
        }
        this.numBox.active = false
        this.latestIdx = this.node.getSiblingIndex()
        this.node.setSiblingIndex(Number.MAX_SAFE_INTEGER)
        lobby.instance.showClickMaskWithNode(this.node, 0, () => {
            this.node.setSiblingIndex(this.latestIdx)
            this.changeStatus(NormalBuildingStatus.normal)
        })
    }

    _changeStatus2Normal() {
        this.node.setScale(1, 1)
        this.building.node.position = new Vec3(this.buildingOffsetX, this.buildingOffsetY - 50)
        this.getComponent(Sprite)!.enabled = false
        this.checkBox.node.active = false
        this.numBox.active = false
        this.newBuilding = false
        this.upgradeFlagIcon.active = this.canUpgrade()
    }


    moveToTiled(x: number, y: number, init: boolean) {
        const currentCellId = calcCellId(x, y)
        if (userInfo.cityInfo.checkUnlockCell(currentCellId, this.buildingConfig!)) {
            return
        }
        const fromX = this.tiledX
        const fromY = this.tiledY
        const tv = this.tiledLayer!.getPositionAt(x, y)!
        this.node.setPosition(new Vec3(tv.x + this.tileSize.width / 2, tv.y + 50))
        this.node.getComponent(UITransform)!.anchorX = this.calculateOriginPercentage(this.buildingConfig!.width, this.buildingConfig!.height)
        this.tiledX = x
        this.tiledY = y
        if (!init) {
            const event = new CityBuildingMove(fromX, fromY, x, y, this.buildingId)
            director.emit(GameEvent.cityBuildingMove, event, this)
        }
    }

    calculateOriginPercentage(w: number, h: number): number {
        return (Math.abs(2 + (h - 1)) / Math.abs((2 + (h - 1)) - (-2 - (w - 1))));
    }


    moveToPosition(x: number, y: number) {
        // 等距坐标转换公式
        if (!this.isInEllipse(x, y)) {
            const tilePosition = this.calcTileOffset(x, y)
            const oldPosition = this.node.position.clone()
            this.moveToTiled(this.tiledX + tilePosition.x, this.tiledY + tilePosition.y, false)
            const newPosition = this.node.position.clone()
            this.currentMoveX -= (newPosition.x - oldPosition.x)
            this.currentMoveY -= (newPosition.y - oldPosition.y)
        }
    }

    calcTileOffset(x: number, y: number): Vec2 {
        const verticalSemiAxis = this.tileSize.height / 2;  // y轴方向半长
        const horizontalSemiAxis = this.tileSize.width / 2; // x轴方向半长
        if (y <= -verticalSemiAxis) return new Vec2(1, 1)
        if (y >= verticalSemiAxis) return new Vec2(-1, -1)
        if (x <= -horizontalSemiAxis) return new Vec2(-1, 1)
        if (x >= horizontalSemiAxis) return new Vec2(1, -1)
        if (x < 0 && y < 0) return new Vec2(0, 1)
        if (x > 0 && y < 0) return new Vec2(1, 0)
        if (x > 0 && y > 0) return new Vec2(0, -1)
        return new Vec2(-1, 0)
    }

    isInEllipse(x: number, y: number): boolean {
        const s = lobby.instance.camera.orthoHeight / 640
        const a = this.tileSize.width / (2 * s);  // x轴半长（长半轴）
        const b = this.tileSize.height / (2 * s);  // y轴半长（短半轴）

        // 计算椭圆方程的值: (x^2 / a^2) + (y^2 / b^2)
        const value = (x * x) / (a * a) + (y * y) / (b * b);

        // 当值 <= 1 时，点在椭圆内或边界上
        return value <= 1;
    }

    cellId(): bigint {
        return calcCellId(this.tiledX, this.tiledY)
    }

    beginUpgrade() {
        this.changeStatus(NormalBuildingStatus.normal)
        console.log('升级完成时间点:', this.buildingItem!.completeAtMs.toNumber())
        console.log('服务器的时间戳:', serverTimeHelper.loadServerTime())
        if (this.buildingItem!.completeAtMs.div(1000).gt(serverTimeHelper.loadServerTime() / 1000)) {
            this.completeAtMsLabel.prefixText = '升级中:'
            this.completeAtMsLabel.setTimeByServerTime(this.buildingItem!.completeAtMs.toNumber())
            this.completeAtMsLabel.onComplete = () => {
                this.finishUpgrade()
            }
        } else {
            this.finishUpgrade()
        }
        this.updateUI(this.buildingItem!.buildingUniqueId)
    }

    beginRemove() {
        this.changeStatus(NormalBuildingStatus.normal)
        console.log('拆除完成时间点:', this.buildingItem!.completeAtMs.toNumber())
        console.log('服务器的时间戳:', serverTimeHelper.loadServerTime())
        if (this.buildingItem!.completeAtMs.div(1000).gt(serverTimeHelper.loadServerTime() / 1000)) {
            this.completeAtMsLabel.prefixText = '拆除中:'
            this.completeAtMsLabel.setTimeByServerTime(this.buildingItem!.completeAtMs.toNumber())
            this.completeAtMsLabel.onComplete = () => {
                this.finishRemove()
            }
        } else {
            this.finishRemove()
        }
        this.updateUI(this.buildingItem!.buildingUniqueId)
    }

    finishUpgrade() {
        this.buildingItem!.completeAtMs = Long.fromNumber(-1);
        this?.scheduleOnce(() => {
            director.emit(GameEvent.cityBuildingCheckUpgrade, new CityBuildingCheckUpgrade(this.buildingItem!))
        }, 0.1)
    }

    finishRemove() {
        this.buildingItem!.completeAtMs = Long.fromNumber(-1);
        this?.scheduleOnce(() => {
            director.emit(GameEvent.cityBuildingCheckRemove, new CityBuildingCheckRemove(this.buildingItem!))
            this.node.destroy()
        }, 0.1)
    }


    private _usableClick: boolean = true

    // 触摸开始事件
    onTouchStart(event: EventTouch) {
        console.log('onTouchBegin', event)
        this._usableClick = true
        this.currentMoveX = 0
        this.currentMoveY = 0
        const touchPos = event.getLocation();
        const buildingScreenPos = lobby.instance.camera.worldToScreen(this.building.node.worldPosition)
        let localPos = touchPos.subtract(buildingScreenPos.toVec2())
        this._usableClick = this.isPointInDiamondArea(localPos);
        console.log('usableClick', localPos, this._usableClick, this.buildingId.toString())
        if (!this._usableClick) {
            console.log('unusable click')
            event.propagationStopped = true
            event.preventSwallow = true
            return
        }
        console.log('click building', this.tiledX, this.tiledY)
        if (this._status == NormalBuildingStatus.edit) {
            if (this.inWhichScrollView != null) {
                this.inWhichScrollView.enabled = false
            }
        }
    }

    // 触摸移动事件
    onTouchMove(event: EventTouch) {
        if (!this.movable || !userInfo.cityInfo.checkInEdit()) return
        if (this._status != NormalBuildingStatus.edit) return
        const startLocation = event.getUIStartLocation()
        const currentLocation = event.getUILocation()
        this.moveToPosition(this.currentMoveX + (currentLocation.x - startLocation.x), this.currentMoveY + (currentLocation.y - startLocation.y))
    }

    // 触摸开始事件
    onTouchEnd(event: EventTouch) {
        console.log('building touch', this.buildingItem, 'click usable', this._usableClick)
        if (this.inWhichScrollView != null) {
            this.inWhichScrollView.enabled = true
        }
        if (!this._usableClick) {
            console.log('unusable click')
            event.propagationStopped = true
            event.preventSwallow = true
            return
        }
        if (this._status == NormalBuildingStatus.normal) {
            if (userInfo.cityInfo.checkInEdit()) {
                director.emit(GameEvent.cityBuildingBeginEdit, new CityBuildingBeginEdit(this))
            } else {
                this.changeStatus(NormalBuildingStatus.in_see)
            }
        }
        if (!userInfo.cityInfo.checkInEdit()) {
            this.specialBuildingWhenClick()
        }
    }

    specialBuildingWhenClick() {
        if (this.buildingId.eq(Long.fromNumber(105))) {
            const fishFryTopNode = lobby.instance.addUIWithClickMask('prefab/common/fish-fry-top', 128, (node) => node.destroy())
            const fishFryTop = fishFryTopNode.getComponent(FishFryTop)!
            fishFryTop.init(this)
            return
        }
        if (this.buildingId.eq(Long.fromNumber(104))) {
            const dormitoryNode = lobby.instance.addUIWithClickMask('prefab/common/dormitory-plane', 128, (node) => node.destroy())
            const dormitoryPlane = dormitoryNode.getComponent(DormitoryPlane)!
            dormitoryPlane.init(this)
            return
        }
        const bac = configsHelper.loadBuildingMixingFormulaConfigs(this.buildingId, this.buildingItem!.level)
        if (bac && bac.showInput.length != 0) {
            this.tryProduce()
            return
        }
    }

    private isPointInDiamondArea(point: Vec2): boolean {
        if (this._status != NormalBuildingStatus.normal) {
            return true
        }
        // 步骤1: 坐标偏移，让原点位于平行四边形中心
        const ut = this.building.getComponent(UITransform)!
        console.log('anchor x', ut.anchorX)
        const a = ut.width * ut.anchorX
        const b = ut.height / 3
        console.log('a = ', a)
        const l1 = (x: number) => x / 2
        const l2 = (x: number) => -x / 2
        const l3 = (x: number) => (x / 2) + (this.tileSize.height * this.buildingConfig!.height)
        const l4 = (x: number) => (-x / 2) + (this.tileSize.height * this.buildingConfig!.width) + b
        const v1 = l1(point.x)
        const v2 = l2(point.x)
        const v3 = l3(point.x)
        const v4 = l4(point.x)
        return (v1 < point.y && v2 < point.y && v3 > point.y && v4 > point.y)
    }

    private isPointInDiamond(normalizedX: number, normalizedY: number): boolean {
        // 将坐标归一化到 [-0.5, 0.5] 范围
        const x = normalizedX - 0.5;
        const y = normalizedY - 0.5;

        // 菱形判断条件：|x| + |y| <= 0.5
        return Math.abs(x) + Math.abs(y) <= 0.5;
    }

    protected onDestroy() {
        this.offEvent()
    }

    update(dt: number) {
    }

    updateUI(buid: Long | undefined) {
        if (this._status == NormalBuildingStatus.show) {
            this._changeStatus2Show()
            return
        }
        if (buid != this.buildingItem?.buildingUniqueId) return
        if (this.buildingItem) {
            const bi = this.buildingItem!
            this.levelLabel!.string = bi.level.toString()
            this.levelBg!.active = !this.buildingConfig!.removable
            const completeAtMsLabelShow = bi.completeAtMs.gt(serverTimeHelper.loadServerTime())
            this.completeAtMsLabel.node.active = completeAtMsLabelShow
            this.completeAtMsLabelBg.node.active = completeAtMsLabelShow
            this.upgradeFlagIcon.active = this.canUpgrade()
            this._tryShowResourcePop()
        } else {
            this.completeAtMsLabel.node.active = false
            this.completeAtMsLabelBg.node.active = false
        }

    }


}